package com.ld.admin.controller.system.codegen;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletException;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.ld.admin.controller.AdminBasicController;
import com.ld.admin.model.system.codegen.CodegenDbsetModel;
import com.ld.admin.service.codegen.CodegenService;
import com.ld.shieldsb.codegen.model.PreferenceModel;
import com.ld.shieldsb.codegen.model.export.ExportParams;
import com.ld.shieldsb.codegen.model.export.ExportResult;
import com.ld.shieldsb.codegen.service.CodeGenService;
import com.ld.shieldsb.codegen.util.PreferenceUtil;
import com.ld.shieldsb.common.core.collections.ListUtils;
import com.ld.shieldsb.common.core.model.Result;
import com.ld.shieldsb.common.core.util.PathUtil;
import com.ld.shieldsb.common.core.util.StringUtils;
import com.ld.shieldsb.common.web.util.Web;
import com.ld.shieldsb.common.web.util.WebUtil;
import com.ld.shieldsb.common.web.util.server.WebServerUtil;
import com.ld.shieldsb.db.model.DBSetInfo;
import com.ld.shieldsb.db.model.DBTableColumnModel;
import com.ld.shieldsb.db.model.DBTableModel;
import com.ld.shieldsb.db.service.DBTabelService;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;

@Api(tags = "代码生成器")
@ConditionalOnProperty(prefix = "modules.sc.system.codegen", name = "enable", havingValue = "true", matchIfMissing = true)
@Controller
@RequestMapping("${shieldsb.adminPath}/system/codegen")
public class CodeGenController extends AdminBasicController<CodegenDbsetModel> {
    @Autowired
    public CodegenService codegenService;

    @ApiOperation(value = "首页", notes = "")
    @RequestMapping(path = "", method = RequestMethod.GET)
    public String index() {
        return "forward:" + adminPath + "/system/codegen/toSearch"; // 跳转搜索页面
    }

    @ApiOperation(value = "到搜索页面", notes = "")
    @RequestMapping(path = "/toSearch", method = RequestMethod.GET)
    public String toSearch() throws ServletException, IOException {
        // 搜索数据库设置
        List<CodegenDbsetModel> dbSetList = basicService.getList(CodegenDbsetModel.class, basicService.getNormalQueryModel());
        request.setAttribute("dbsets", dbSetList);
        return "a/system/codegen/search";
    }

    @ApiOperation(value = "搜索表主要信息", notes = "")
    @RequestMapping(path = "/tables", method = RequestMethod.POST)
    public String tables() throws ServletException, IOException {
        setAttributes();
        Long dbConnId = getLong("conn");
        DBSetInfo dbSetInfo = codegenService.getDbSetInfo(dbConnId);
        DBTabelService service = DBTabelService.getInstance(dbSetInfo);
        // 验证是否可以连接
        Result result = codegenService.testCon(dbSetInfo);
        if (result.getSuccess()) {
            String tableName = getString("tableName");
            List<DBTableModel> dbList = service.getTables(tableName);
            request.setAttribute("list", dbList); // list
        } else {
            Web.Response.forwardError(result.getMessage()); // 跳转错误页
        }
        return "a/system/codegen/tables";
    }

    @ApiOperation(value = "搜索表字段信息", notes = "")
    @RequestMapping(path = "/tablecols", method = RequestMethod.POST)
    public String tablecols() throws ServletException, IOException {
        setAttributes();
        request.setAttribute("projectPath", PathUtil.getProjectPath());
        String tableName = getString("tableName");
        String className = CodeGenService.parseClassName(tableName); // 表名转类名
        request.setAttribute("className", className);
        Long dbConnId = getLong("conn");
        DBSetInfo dbSetInfo = codegenService.getDbSetInfo(dbConnId);
        DBTabelService service = DBTabelService.getInstance(dbSetInfo);
        List<DBTableColumnModel> tablCols = service.getTableColumn(tableName);
        if (ListUtils.isNotEmpty(tablCols)) {
            tablCols.forEach(tabCol -> {
                tabCol.setExportColName(CodeGenService.parseFieldName(tabCol.getColumnName())); // 处理导出名称
            });

        }
        request.setAttribute("list", tablCols); // list

        PreferenceModel preferenceModel = PreferenceUtil.getPreferenceModel(Web.Util.getSessionUserId(request) + "");
        String outDic = PathUtil.getProjectPath();
        if (StringUtils.isNotBlank(preferenceModel.getSrcDir())) {
            outDic = preferenceModel.getSrcDir();
        }
        request.setAttribute("outdic", outDic);
        request.setAttribute("preference", preferenceModel);

        return "a/system/codegen/tablecols";
    }

    @ApiOperation(value = "生成代码", notes = "")
    @RequestMapping(path = "/gen", method = RequestMethod.POST)
    // 返回json格式
    @ResponseBody
    public Object codeGen(ExportParams model) throws ServletException, IOException {
        String host = WebServerUtil.getHost();
        String ipAddr = WebUtil.getIpAddr(request);
        List<String> outtypes = getList("outtype");
        if (ListUtils.isEmpty(outtypes)) {
            return Web.Response.error("没有选择生成类型！");
        }
        String flag = "";
        Map<String, String> object = new HashMap<>();
        try {
            boolean isLocal = false;
            // 本地生成
            if (host.equals(ipAddr) || ipAddr.equals("127.0.0.1") || ipAddr.equals("localhost") || ipAddr.equals("0:0:0:0:0:0:0:1") // ip6
                    || ipAddr.equals(WebUtil.getMachineName())) {
                isLocal = true;
            } else { // 远程文件，返回压缩包地址
                model.setOutDir(PathUtil.getTmpDir()); // 更改输出目录为临时目录，防止恶意覆盖正常目录
            }
            ExportResult result = codegenService.getCreateCodeStr(model, outtypes);

            String outDic = model.getOutDir();

            if (isLocal) { // 本地生成
                flag = "共生成文件" + result.getFileSize() + "个。请到路径：" + outDic + "下查看！";
            } else { // 远程文件，返回压缩包地址
                log.warn("host:" + host + " ip:" + ipAddr + " " + PathUtil.getTmpDir());
                model.setOutDir(PathUtil.getTmpDir());
                if (result.getFileSize() > 0) {
                    result.getZipFile(model.getOutDir(), PathUtil.getTmpDir() + "/" + model.getTableName() + ".zip");
                }
                // 输出链接到页面
                object.put("target", ".downloadZipCode");
                object.put("href", context.getAttribute("ctxPathA") + "/system/codegen/download?tn=" + model.getTableName());
                session.setAttribute("codeDown", model.getTableName());
                flag = "共生成文件" + result.getFileSize() + "个。点击页面上的下载链接进行下载！";

            }

            PreferenceUtil.addRecentSrcDir(outDic, Web.Util.getSessionUserId(request) + ""); // 保存个人偏好
        } catch (Exception e) {
            log.error("生成代码失败！", e);
            return Web.Response.error("生成代码失败！" + e.getMessage());
        }
        return Web.Response.success("生成代码完成，请复制到项目中检查代码是否正确！" + flag, object);
    }

    @RequestMapping(value = "/download")
    public ResponseEntity<FileSystemResource> listExport(String proNo) {
        String tableName = getString("tn");
        File file = new File(PathUtil.getTmpDir() + "/" + tableName + ".zip");
        return codegenService.downFile(file);
    }

    @ApiOperation(value = "预览生成代码", notes = "")
    @RequestMapping(path = "/preview", method = RequestMethod.POST)
    public String codePreview(ExportParams model) throws ServletException, IOException {
        model.setPreview(true); // 设置为预览，不生成代码
        List<String> outtypes = getList("outtype");
        if (ListUtils.isEmpty(outtypes)) {
            return Web.Response.error("没有选择生成类型！").toString();
        }
        try {
            ExportResult result = codegenService.getCreateCodeStr(model, outtypes);
            request.setAttribute("model", result);
            String outDic = model.getOutDir();
            PreferenceUtil.addRecentSrcDir(outDic, Web.Util.getSessionUserId(request) + ""); // 保存个人偏好
        } catch (Exception e) {
            log.error("生成代码失败！", e);
            return Web.Response.error("生成预览代码失败！" + e.getMessage()).toString();
        }
        return "a/system/codegen/preview";
    }

}
